#include <arpa/inet.h>
#include <atomic>
#include <cstring>
#include <exception>
#include <netdb.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <string>
#include <sys/socket.h>
#include <sys/types.h>
#include <thread>
#include <unistd.h>
#include <vector>

std::atomic<bool> g_running{false};

void handleSignal(int signo) { throw std::runtime_error((char *)"程序退出"); }

void clientDataProcess(int client_fp, char *client_ip, int client_port) {
    printf("New clientDataProcess. ip: %s port: %d\n", client_ip, client_port);
    int buflen = 1024;
    char *buffer = (char *)malloc(buflen);
    while (g_running.load()) {
        ssize_t recv_len = recv(client_fp, buffer, buflen, 0);
        if (recv_len > 0) {
            printf("Recv data. len = %lu, msg: %s\n", recv_len, buffer);
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
    free(buffer);
    close(client_fp);
}

int main(int argv, char **argc) {
    signal(SIGINT, handleSignal);

    int fp = socket(AF_INET, SOCK_STREAM, 0);
    if (fp == -1) {
        printf("套接字创建失败.\n");
        return -1;
    }

    struct sockaddr_in addr;
    const char *ip = (char *)("10.50.34.149");
    int port = 8088;
    addr.sin_family = AF_INET;
    if (strlen(ip) > 0) {
        addr.sin_addr.s_addr = inet_addr(ip);
    } else {
        addr.sin_addr.s_addr = htonl(INADDR_ANY); // INADDR_ANY对应0.0.0,0
    }
    addr.sin_port = htons(port);
    if (bind(fp, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
        printf("绑定ip: %s, 端口%d失败.\n", ip, 8088);
        return -1;
    }
    constexpr int max_client_count = 5;

    if (listen(fp, max_client_count) == -1) {
        printf("监听失败.\n");
        return -1;
    }
    printf("服务器启动成功，ip: %s, port: %d\n", ip, port);

    std::thread threads[max_client_count];
    g_running.store(true);
    int idx = 0;
    try {
        while (g_running.load()) {
            struct sockaddr_in clientaddr;
            socklen_t addrlen = sizeof(struct sockaddr_in);
            int client_fp;
            printf("开始监听客户端\n");
            if ((client_fp = accept(fp, (struct sockaddr *)&clientaddr,
                                    &addrlen)) == -1) {
                printf("监听失败\n");
            }
            printf("接受到新的客户端\n");
            char *client_ip = inet_ntoa(clientaddr.sin_addr);
            int client_port = ntohs(clientaddr.sin_port);
            printf("New client#%d connected. ip: %s port: %d\n", client_fp,
                   client_ip, client_port);

            threads[idx++] = std::thread(clientDataProcess, client_fp,
                                         client_ip, client_port);
            if (idx >= max_client_count) {
                break;
            }
        }

    } catch (const std::exception &e) {
        printf("接受到一个异常(%s)，开始关闭服务器.\n", e.what());
    }

    printf("关闭服务器,释放资源\n");

    g_running.store(false);
    for (int i = 0; i < idx; i++) {
        threads[i].join();
    }
    close(fp);

    return 0;
}
